#Region "Imports Directives"

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports C4F.DevKit.Bluetooth.ObjectExchange

#End Region

Namespace C4F.DevKit.Bluetooth

    Namespace FileTransferProfile

        ''' <summary>
        ''' Contains methods for performing file/folder operations on remote
        ''' device.
        ''' </summary>
        Public Class BluetoothFTPManager
            Inherits ComponentModel.Component

#Region "Private Members"

            ''' <summary>
            ''' Network Stream used for communication with remote service
            ''' </summary>
            Private netwrkStream As Net.Sockets.NetworkStream

            ''' <summary>
            ''' Connection Id  used in all subsequent requests.
            ''' </summary>
            Private connectionId() As Byte

            ''' <summary>
            ''' Maximum Packet Length that the remote device accepts.
            ''' </summary>
            Private maxPacketLength As UShort

            ''' <summary>
            ''' List of pending FTPReqests.
            ''' </summary>
            Private requestQueue As List(Of FTPRequest)

            ''' <summary>
            ''' A background worker that handles asynchronous FTP requests.
            ''' </summary>
            Private WithEvents asyncOperationHandler As ComponentModel.BackgroundWorker

            ''' <summary>
            ''' The asynchronous FTP request that is being handled by 
            ''' asyncOperationHandler.
            ''' </summary>
            Private runningAsyncRequest As FTPRequest

#End Region

#Region "Public Events and Delegates"

            ''' <summary>
            ''' The event handler for an GetFileBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Get File operation begins.
            ''' </param>
            Public Delegate Sub GetFileBeginEventHandler(ByVal sender As Object, _
                                                          ByVal e As GetFileBeginEventArgs)

            ''' <summary>
            ''' This event is fired when a Get File operation begins.
            ''' </summary>
            Public Event GetFileBegin As GetFileBeginEventHandler

            ''' <summary>
            ''' The event handler for a GetFileCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Get File operation completes.
            ''' </param>
            Public Delegate Sub GetFileCompletedEventHandler(ByVal sender As Object, _
                                                              ByVal e As GetFileCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a Get File operation completes.
            ''' </summary>
            Public Event GetFileCompleted As GetFileCompletedEventHandler

            ''' <summary>
            ''' The event handler for a GetFolderBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Get Folder operation begins.
            ''' </param>
            Public Delegate Sub GetFolderBeginEventHandler(ByVal sender As Object, _
                                                            ByVal e As GetFolderBeginEventArgs)

            ''' <summary>
            ''' This event is fired when an Get Folder operation begins.
            ''' </summary>
            Public Event GetFolderBegin As GetFolderBeginEventHandler

            ''' <summary>
            ''' The event handler for a GetFolderCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Get Folder operation 
            ''' completes.</param>
            Public Delegate Sub GetFolderCompletedEventHandler(ByVal sender As Object, _
                                                                ByVal e As GetFolderCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a Get Folder operation completes.
            ''' </summary>
            Public Event GetFolderCompleted As GetFolderCompletedEventHandler

            ''' <summary>
            ''' The event handler for a SendFileBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Send File operation begins.
            ''' </param>
            Public Delegate Sub SendFileBeginEventHandler(ByVal sender As Object, _
                                                           ByVal e As SendFileBeginEventArgs)

            ''' <summary>
            ''' This event is fired when an Send File operation begins.
            ''' </summary>
            Public Event SendFileBegin As SendFileBeginEventHandler

            ''' <summary>
            ''' The event handler for a SendFileCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Send File operation 
            ''' completes.</param>
            Public Delegate Sub SendFileCompletedEventHandler(ByVal sender As Object, _
                                                               ByVal e As SendFileCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a Send File operation completes.
            ''' </summary>
            Public Event SendFileCompleted As SendFileCompletedEventHandler

            ''' <summary>
            ''' The event handler for a SendFolderBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Send Folder operation begins.
            ''' </param>
            Public Delegate Sub SendFolderBeginEventHandler(ByVal sender As Object, _
                                                             ByVal e As SendFolderBeginEventArgs)

            ''' <summary>
            ''' This event is fired when a SendFolder operation begins.
            ''' </summary>
            Public Event SendFolderBegin As SendFolderBeginEventHandler

            ''' <summary>
            ''' The event handler for a SendFolderCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Send Folder operation 
            ''' completes.</param>
            Public Delegate Sub SendFolderCompletedEventHandler(ByVal sender As Object, _
                                                                 ByVal e As SendFolderCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a Send Folder operation completes.
            ''' </summary>
            Public Event SendFolderCompleted As SendFolderCompletedEventHandler

            ''' <summary>
            ''' The event handler for a DeleteFileBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Delete File operation begins.
            ''' </param>
            Public Delegate Sub DeleteFileBeginEventHandler(ByVal sender As Object, _
                                                             ByVal e As DeleteFileBeginEventArgs)

            ''' <summary>
            ''' This event is fired when an Delete File operation begins.
            ''' </summary>
            Public Event DeleteFileBegin As DeleteFileBeginEventHandler

            ''' <summary>
            ''' The event handler for an DeleteFileCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Delete File operation 
            ''' completes.</param>
            Public Delegate Sub DeleteFileCompletedEventHandler(ByVal sender As Object, _
                                                                 ByVal e As DeleteFileCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a DeleteFile operation completes.
            ''' </summary>
            Public Event DeleteFileCompleted As DeleteFileCompletedEventHandler

            ''' <summary>
            ''' The event handler for an DeleteFolderBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Delete Folder operation 
            ''' begins.</param>
            Public Delegate Sub DeleteFolderBeginEventHandler(ByVal sender As Object, _
                                                               ByVal e As DeleteFolderBeginEventArgs)

            ''' <summary>
            ''' This event is fired when an DeleteFolder operation begins.
            ''' </summary>
            Public Event DeleteFolderBegin As DeleteFolderBeginEventHandler

            ''' <summary>
            ''' The event handler for an DeleteFolderCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Delete Folder operation 
            ''' completes.</param>
            Public Delegate Sub DeleteFolderCompletedEventHandler(ByVal sender As Object, _
                                                                   ByVal e As DeleteFolderCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a DeleteFolder operation completes.
            ''' </summary>
            Public Event DeleteFolderCompleted As DeleteFolderCompletedEventHandler

            ''' <summary>
            ''' The event handler for a CreateFolderBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Create Folder operation 
            ''' begins.</param>
            Public Delegate Sub CreateFolderBeginEventHandler(ByVal sender As Object, _
                                                               ByVal e As CreateFolderBeginEventArgs)

            ''' <summary>
            ''' This event is fired when a CreateFolder operation begins.
            ''' </summary>
            Public Event CreateFolderBegin As CreateFolderBeginEventHandler

            ''' <summary>
            ''' The event handler for a CreateFolderCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a Create Folder operation 
            ''' completes.</param>
            Public Delegate Sub CreateFolderCompletedEventHandler(ByVal sender As Object, _
                                                                   ByVal e As CreateFolderCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a CreateFolder operation completes.
            ''' </summary>
            Public Event CreateFolderCompleted As CreateFolderCompletedEventHandler

            ''' <summary>
            ''' The event handler for a SetCurrentDirectoryBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a SetCurrentDirectory operation
            ''' begins.</param>
            Public Delegate Sub SetCurrentDirectoryBeginEventHandler(ByVal sender As Object, _
                                                                      ByVal e As SetCurrentDirectoryBeginEventArgs)

            ''' <summary>
            ''' This event is fired when a SetCurrentDirectory operation begins.
            ''' </summary>
            Public Event SetCurrentDirectoryBegin As SetCurrentDirectoryBeginEventHandler

            ''' <summary>
            ''' The event handler for a SetCurrentDirectoryCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a SetCurrentDirectory operation 
            ''' completes.</param>
            Public Delegate Sub SetCurrentDirectoryCompletedEventHandler(ByVal sender As Object, _
                                                                          ByVal e As SetCurrentDirectoryCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a SetCurrentDirectory operation completes.
            ''' </summary>
            Public Event SetCurrentDirectoryCompleted As SetCurrentDirectoryCompletedEventHandler


            ''' <summary>
            ''' The event handler for a GetFolderListingBegin event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a GetFolderListing operation
            ''' begins.</param>
            Public Delegate Sub GetFolderListingBeginEventHandler(ByVal sender As Object, _
                                                                   ByVal e As GetFolderListingBeginEventArgs)

            ''' <summary>
            ''' This event is fired when a GetFolderListing operation begins.
            ''' </summary>
            Public Event GetFolderListingBegin As GetFolderListingBeginEventHandler

            ''' <summary>
            ''' The event handler for a GetFolderListingCompleted event.
            ''' </summary>
            ''' <param name="sender">The sender of the event.</param>
            ''' <param name="e">EventArgs when a GetFolderListing operation
            ''' completes.</param>
            Public Delegate Sub GetFolderListingCompletedEventHandler(ByVal sender As Object, _
                                                                       ByVal e As GetFolderListingCompletedEventArgs)

            ''' <summary>
            ''' This event is fired when a GetFolderListing operation completes.
            ''' </summary>
            Public Event GetFolderListingCompleted As GetFolderListingCompletedEventHandler

#End Region

#Region "Public Functions"

#Region "Constructor"

            ''' <summary>
            ''' Initializes a FTPManager object.
            ''' </summary>
            Public Sub New()

                ' Initialize request queue and background worker.
                InitializeFTPManager()

            End Sub

            ''' <summary>
            ''' Initializes a FTPManager object.
            ''' </summary>
            ''' <param name="networkStream">Network stream used for 
            ''' communication with remote service.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to the method that does not accept it as a valid argument.
            ''' </exception>            
            Public Sub New(ByVal networkStream As Net.Sockets.NetworkStream)

                If networkStream Is Nothing Then
                    Throw New ArgumentNullException(FTPMessages.ErrorMsgNullNetworkStream)
                End If

                Me.netwrkStream = networkStream

                ' Initialize request queue and background worker.
                InitializeFTPManager()

            End Sub

#End Region

#Region "Asynchronous Methods"

            ''' <summary>
            ''' Asynchronous operation for pulling a file from remote device
            ''' </summary>
            ''' <param name="remoteFilePath">Location of the file to be pulled 
            ''' from remote device.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the asynchronous request.</param>        
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a GetFile operation.
            ''' </exception>
            Public Sub GetFileAsync(ByVal remoteFilePath As String, ByVal userState As Object)

                ' Verify if a valid value has been provided for remoteFilePath
                ' argument.                
                If String.IsNullOrEmpty(remoteFilePath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFilePath)
                End If

                If remoteFilePath.EndsWith("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, _
                                                FTPMessages.RemoteFilePath)
                End If


                ' Verify if connectionId is not null.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream property is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.GetFile, userState, _
                                                        remoteFilePath))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for pulling a folder from remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder to be pulled 
            ''' from remote device.</param>
            ''' <param name="localFolderPath">Location where pulled folder will
            ''' be stored on local device.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a GetFolder operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub GetFolderAsync(ByVal remoteFolderPath As String, _
                                       ByVal localFolderPath As String, ByVal userState As Object)

                ' Verify if remoteFolderPath is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If


                ' If the remoteFolderPath ends with a directory seperator 
                ' then remove it
                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath <> "\" Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if localFolderPath is valid.
                If String.IsNullOrEmpty(localFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.LocalFolderPath)
                End If

                If Not IO.Directory.Exists(localFolderPath) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidLocalFolderPath, _
                                                FTPMessages.LocalFolderPath)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.GetFolder, userState, _
                                                        remoteFolderPath, localFolderPath))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for pushing a file on to remote device.
            ''' </summary>
            ''' <param name="localFilePath">Location of file on local device 
            ''' that has to be pushed on to remote device.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SendFile operation.
            ''' </exception>            
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SendFileAsync(ByVal localFilePath As String, ByVal userState As Object)

                ' Verify if the specified localFilePath is valid.
                If String.IsNullOrEmpty(localFilePath) Then
                    Throw New ArgumentNullException(FTPMessages.LocalFilePath)
                End If

                If Not IO.File.Exists(localFilePath) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidLocalFilePath, FTPMessages.LocalFilePath)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.SendFile, userState, localFilePath))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for pushing a file on to remote device.
            ''' </summary>
            ''' <param name="fileContents">Memory Stream containing contents 
            ''' of the file to be pushed on to remote device.</param>
            ''' <param name="fileName">Name of the file which will be created 
            ''' on remote device.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>         
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SendFile operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SendFileAsync(ByVal fileContents As IO.MemoryStream, ByVal fileName As String, ByVal userState As Object)

                ' Verify if fileContents is valid.
                If fileContents Is Nothing Then
                    Throw New ArgumentNullException(FTPMessages.FileContents)
                End If

                ' Verify if fileName is valid.
                If String.IsNullOrEmpty(fileName) Then
                    Throw New ArgumentNullException(FTPMessages.FileName)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.SendFile, userState, fileName, fileContents))

            End Sub

            '''<summary>
            '''Asynchronous operation for pushing a folder on to remote device.
            '''</summary>
            '''<param name="localFolderPath">Location of folder on local device 
            '''that has to be pushed on to remote device.</param>
            '''<param name="userState">A unique object which can be used to 
            '''keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SendFolder operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SendFolderAsync(ByVal localFolderPath As String, ByVal userState As Object)

                ' Verify if localFolderPath is valid.
                If String.IsNullOrEmpty(localFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.LocalFolderPath)
                End If

                If Not IO.Directory.Exists(localFolderPath) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidLocalFolderPath, FTPMessages.LocalFolderPath)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.SendFolder, userState, localFolderPath))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for deleting a file from remote device.
            ''' </summary>
            ''' <param name="remoteFilePath">Location of file on remote device 
            ''' that has to be deleted.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a DeleteFile operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub DeleteFileAsync(ByVal remoteFilePath As String, ByVal userState As Object)

                Dim fileName As String = String.Empty

                ' Verify if remoteFilePath is valid.
                If String.IsNullOrEmpty(remoteFilePath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFilePath)
                End If

                If remoteFilePath.EndsWith("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, FTPMessages.RemoteFilePath)
                End If


                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue.
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.DeleteFile, userState, remoteFilePath))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for deleting a folder from remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder on remote 
            ''' device that has to be deleted.</param>
            ''' <param name="deleteSubDirectories">Flag indicating if sub-folders
            ''' folders have to be deleted.If true then deletes sub-folders else 
            ''' deletes only specified folder.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a DeleteFolder operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub DeleteFolderAsync(ByVal remoteFolderPath As String, _
                                          ByVal deleteSubDirectories As Boolean, ByVal userState As Object)

                ' Verify if specified remoteFolderPath is valid
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.Equals("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgDeleteRootDir, FTPMessages.RemoteFolderPath)
                End If


                If remoteFolderPath.EndsWith("\") Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.DeleteFolder, _
                                                        userState, remoteFolderPath, deleteSubDirectories))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for creating a folder on remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of the folder to be 
            ''' created on remote device.The last folder in this path is assumed
            ''' to be the folder which has to be created.</param>
            ''' <param name="createParentDirectories">Flag indicating if non-existing
            ''' parent folders have to be created.If true then creates 
            ''' non-existing parent folders. If false and if parent folder doesn't exist 
            ''' then an exception is raised.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a CreateFolder operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub CreateFolderAsync(ByVal remoteFolderPath As String, _
                                          ByVal createParentDirectories As Boolean, ByVal userState As Object)

                ' Verify if the remoteFolderPath is valid
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.Equals("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgCreateRootDir, FTPMessages.RemoteFolderPath)
                End If



                If remoteFolderPath.EndsWith("\") Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue.
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.CreateFolder, userState, remoteFolderPath, createParentDirectories))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for setting the current directory 
            ''' on remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of remote folder 
            ''' to be set as current directory.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>    
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SetCurrentDirectory operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SetCurrentDirectoryAsync(ByVal remoteFolderPath As String, ByVal userState As Object)

                ' Verify if Path is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath.Length > 2 Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue.
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.SetCurrentDirectory, userState, remoteFolderPath))

            End Sub

            ''' <summary>
            ''' Asynchronous operation for getting the folder listing of a 
            ''' remote folder.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder on remote 
            ''' device.</param>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>       
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a GetFolderListing operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub GetFolderListingAsync(ByVal remoteFolderPath As String, ByVal userState As Object)

                ' Verify if remoteFolderPath is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath.Length > 2 Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Add request to queue.
                AddRequestToRequestQueue(New FTPRequest(FTPRequestType.GetFolderListing, userState, remoteFolderPath))

            End Sub

            ''' <summary>
            ''' Cancels an asynchronous operation.
            ''' </summary>
            ''' <param name="userState">A unique object which can be used to 
            ''' keep track of the request.</param>
            ''' <exception cref="InvalidOperationException">Thrown when 
            ''' an error occurs while trying to cancel a non-existent FTPRequest.</exception>
            Public Sub CancelAsync(ByVal userState As Object)

                If userState Is Nothing Then
                    Throw New ArgumentNullException(FTPMessages.UserState)
                End If

                Dim invalidCancel As Boolean = True
                ' Acquire an exclusive lock on the requestQueue. 
                Threading.Monitor.Enter(Me.requestQueue)

                Try
                    ' Check whether this operation is currently executing.
                    If Me.asyncOperationHandler.IsBusy AndAlso Me.runningAsyncRequest _
                    IsNot Nothing AndAlso Me.runningAsyncRequest.UserState.Equals(userState) Then

                        Me.asyncOperationHandler.CancelAsync()
                        invalidCancel = False

                    Else
                        ' Search for the operation in the queue.
                        For Each request As FTPRequest In Me.requestQueue

                            If request.UserState.Equals(userState) Then

                                ' Remove it from queue.
                                Me.requestQueue.Remove(request)
                                invalidCancel = False
                                Exit For

                            End If

                        Next

                    End If

                Finally
                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.requestQueue)
                End Try

                ' The userState was not found. Raise a InvalidOperationException 
                ' exception
                If invalidCancel Then
                    Throw New InvalidOperationException(FTPMessages.ErrorMsgInvalidUserState)
                End If

            End Sub

#End Region

#Region "Synchronous Methods"

            ''' <summary>
            ''' Synchronous operation for pulling a file from remote device.
            ''' </summary>
            ''' <param name="remoteFilePath">Location of the file to be pulled
            ''' from remote device.</param>   
            ''' <returns>Contents of the pulled file.</returns>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a GetFile operation.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Function GetFile(ByVal remoteFilePath As String) As Byte()

                Dim fileStream As Byte() = Nothing

                ' Verify if the remoteFilePath is valid.
                If String.IsNullOrEmpty(remoteFilePath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFilePath)
                End If

                If remoteFilePath.EndsWith("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, FTPMessages.RemoteFilePath)
                End If

                ' Verify if the connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                RaiseEvent GetFileBegin(Me, New GetFileBeginEventArgs(remoteFilePath, Nothing))

                ' Raise the GetFileBegin Event.              

                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    ' Get the file object and return byte array containing 
                    ' the file contents.
                    fileStream = GetFileObject(remoteFilePath)
                    ' Raise the GetFileCompleted Event
                    RaiseEvent GetFileCompleted(Me, New GetFileCompletedEventArgs(remoteFilePath, _
                                                                                  fileStream, Nothing, False, Nothing))
                    Return fileStream

                Catch ex As Exception

                    RaiseEvent GetFileCompleted(Me, New GetFileCompletedEventArgs(remoteFilePath, _
                                                                                  fileStream, ex, False, Nothing))

                    ' Raise the GetFileCompleted event
                    Throw New FTPException(FTPMessages.ErrorMsgGetFile, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Function

            ''' <summary>
            ''' Synchronous operation for pulling a folder from remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder to be pulled 
            ''' from remote device.</param>
            ''' <param name="localFolderPath">Location where pulled folder will
            ''' be stored on local device.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a GetFolder operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub GetFolder(ByVal remoteFolderPath As String, ByVal localFolderPath As String)

                ' Verify if remoteFolderPath is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath <> "\" Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if localFolderPath is valid.
                If String.IsNullOrEmpty(localFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.LocalFolderPath)
                End If

                If Not IO.Directory.Exists(localFolderPath) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidLocalFolderPath, FTPMessages.LocalFolderPath)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If
                RaiseEvent GetFolderBegin(Me, New GetFolderBeginEventArgs(remoteFolderPath, localFolderPath, Nothing))

                ' Raise the GetFolderBegin event

                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)


                Try
                    ' Call GetFolderObject function which performs the actual task of
                    ' pulling a folder.

                    GetFolderObject(remoteFolderPath, localFolderPath)

                    ' Raise the GetFolderCompleted event
                    RaiseEvent GetFolderCompleted(Me, New GetFolderCompletedEventArgs(remoteFolderPath, _
                                                                                      localFolderPath, Nothing, False, Nothing))

                Catch ex As Exception

                    RaiseEvent GetFolderCompleted(Me, New GetFolderCompletedEventArgs(remoteFolderPath, _
                                                                                      localFolderPath, ex, False, Nothing))
                    ' Raise the GetFolderCompleted event
                    Throw New FTPException(FTPMessages.ErrorMsgGetFolder, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for pushing a file on remote device.
            ''' </summary>
            ''' <param name="localFilePath">Location of file on local device 
            ''' that has to be pushed on to remote device.</param>        
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SendFile operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SendFile(ByVal localFilePath As String)

                ' Verify if the specified localFilePath is valid.
                If String.IsNullOrEmpty(localFilePath) Then
                    Throw New ArgumentNullException(FTPMessages.LocalFilePath)
                End If

                If Not IO.File.Exists(localFilePath) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidLocalFilePath, FTPMessages.LocalFilePath)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                RaiseEvent SendFileBegin(Me, New SendFileBeginEventArgs(localFilePath, Nothing))

                ' Raise the SendFileBegin event
                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)


                Try
                    ' Call SendFileObject function which performs the actual 
                    ' task of pushing file on remote device.
                    SendFileObject(localFilePath)

                    ' Raise the SendFileCompleted event.
                    RaiseEvent SendFileCompleted(Me, New SendFileCompletedEventArgs(localFilePath, _
                                                                                    Nothing, False, Nothing))

                Catch ex As Exception

                    RaiseEvent SendFileCompleted(Me, New SendFileCompletedEventArgs(localFilePath, ex, _
                                                                                    False, Nothing))
                    ' Raise the SendFileCompleted event.

                    Throw New FTPException(FTPMessages.ErrorMsgSendFile, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for pushing a file on remote device.
            ''' </summary>
            ''' <param name="fileContents">Memory Stream containing the contents
            ''' of the file.</param>        
            ''' <param name="fileName">Name of the file which will be created on
            ''' remote device.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SendFile operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>       
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SendFile(ByVal fileContents As IO.MemoryStream, ByVal fileName As String)

                ' Verify if fileContents is valid.
                If fileContents Is Nothing Then
                    Throw New ArgumentNullException(FTPMessages.FileContents)
                End If

                ' Verify if fileName is valid.
                If String.IsNullOrEmpty(fileName) Then
                    Throw New ArgumentNullException(FTPMessages.FileName)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                RaiseEvent SendFileBegin(Me, New SendFileBeginEventArgs(fileName, Nothing))

                ' Raise the SendFileBegin event
                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try

                    ' Call SendFileObject function which performs the actual 
                    ' task of pushing file on remote device.                   
                    SendFileObject(fileContents, fileName)

                    ' Raise the SendFileCompleted event.
                    RaiseEvent SendFileCompleted(Me, New SendFileCompletedEventArgs(fileName, _
                                                                                    Nothing, False, Nothing))

                Catch ex As Exception

                    RaiseEvent SendFileCompleted(Me, New SendFileCompletedEventArgs(fileName, _
                                                                                    Nothing, False, Nothing))
                    ' Raise the SendFileCompleted event.                    

                    Throw New FTPException(FTPMessages.ErrorMsgSendFile, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for pushing a folder to remote device.
            ''' </summary>
            ''' <param name="localFolderPath">Location of folder on local device
            ''' that has to be pushed on to remote device.</param>       
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SendFolder operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SendFolder(ByVal localFolderPath As String)

                ' Verify if localFolderPath is valid.
                If String.IsNullOrEmpty(localFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.LocalFolderPath)
                End If

                If Not IO.Directory.Exists(localFolderPath) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidLocalFolderPath, FTPMessages.LocalFolderPath)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                RaiseEvent SendFolderBegin(Me, New SendFolderBeginEventArgs(localFolderPath, Nothing))

                ' Raise the SendFolderBegin event.

                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)


                Try

                    ' Call SendFileObject function which performs the actual 
                    ' task of pushing a folder on remote device.                               
                    SendFolderObject(localFolderPath)

                    ' Raise the SendFolderCompleted event.
                    RaiseEvent SendFolderCompleted(Me, New SendFolderCompletedEventArgs(localFolderPath, _
                                                                                        Nothing, False, Nothing))

                Catch ex As Exception

                    RaiseEvent SendFolderCompleted(Me, New SendFolderCompletedEventArgs(localFolderPath, ex, _
                                                                                        False, Nothing))
                    ' Raise the SendFolderCompleted Event
                    Throw New FTPException(FTPMessages.ErrorMsgSendFolder, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for deleting a file from remote device.
            ''' </summary>
            ''' <param name="remoteFilePath">Location of file on remote device 
            ''' that has to be deleted.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a DeleteFile operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub DeleteFile(ByVal remoteFilePath As String)

                ' Verify if remoteFilePath is valid.
                If String.IsNullOrEmpty(remoteFilePath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFilePath)
                End If

                If remoteFilePath.EndsWith("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, _
                                                FTPMessages.RemoteFilePath)
                End If


                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                RaiseEvent DeleteFileBegin(Me, New DeleteFileBeginEventArgs(remoteFilePath, Nothing))

                ' Raise the DeleteFileBegin event
                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)


                Try
                    ' Call DeleteFileObject function which performs the actual 
                    ' task of deleting a folder on remote device.      
                    DeleteFileObject(remoteFilePath)

                    ' Raise the DeleteFileCompleted event
                    RaiseEvent DeleteFileCompleted(Me, New DeleteFileCompletedEventArgs(remoteFilePath, _
                                                                                        Nothing, False, Nothing))

                Catch ex As Exception

                    RaiseEvent DeleteFileCompleted(Me, New DeleteFileCompletedEventArgs(remoteFilePath, ex, _
                                                                                        False, Nothing))

                    ' Raise the DeleteFileCompleted event
                    Throw New FTPException(FTPMessages.ErrorMsgDeleteFile, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for deleting a folder from remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder on remote 
            ''' device that has to be deleted.</param>
            ''' <param name="deleteSubDirectories">Flag indicating if sub-folders
            ''' folders have to be deleted.If true then deletes sub-folders else 
            ''' deletes only specified folder.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a DeleteFolder operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub DeleteFolder(ByVal remoteFolderPath As String, ByVal deleteSubDirectories As Boolean)

                ' Verify if specified path is valid
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.Equals("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgDeleteRootDir, FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.EndsWith("\") Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If
                RaiseEvent DeleteFolderBegin(Me, New DeleteFolderBeginEventArgs _
                                             (remoteFolderPath, deleteSubDirectories, Nothing))

                ' Raise the DeleteFolderCompleted event
                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    DeleteFolderObject(remoteFolderPath, deleteSubDirectories)

                    ' Raise the DeleteFolderCompleted event
                    RaiseEvent DeleteFolderCompleted(Me, New DeleteFolderCompletedEventArgs _
                                                     (remoteFolderPath, deleteSubDirectories, _
                                                      Nothing, False, Nothing))

                Catch ex As Exception
                    RaiseEvent DeleteFolderCompleted(Me, New DeleteFolderCompletedEventArgs _
                                                     (remoteFolderPath, deleteSubDirectories, _
                                                      ex, False, Nothing))

                    ' Raise the DeleteFolderCompleted event
                    Throw New FTPException(FTPMessages.ErrorMsgDeleteFolder, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for creating a folder on remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of the folder to be 
            ''' created on remote device.The last folder in this path is assumed
            ''' to be the folder which has to be created.</param>
            ''' <param name="createParentDirectories">Flag indicating if non-existing
            ''' parent folders have to be created.If true then creates 
            ''' non-existing parent folders. If false and if parent folder doesn't exist 
            ''' then an exception is raised.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a CreateFolder operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub CreateFolder(ByVal remoteFolderPath As String, _
                                     ByVal createParentDirectories As Boolean)

                ' Verify if the remoteFolderPath is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.Equals("\") Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgCreateRootDir, _
                                                FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.EndsWith("\") Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if the connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If
                RaiseEvent CreateFolderBegin(Me, New CreateFolderBeginEventArgs _
                                             (remoteFolderPath, createParentDirectories, Nothing))

                ' Raise the CreateFolderBegin event
                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    ' Call CreateFolderStructure function which performs the actual 
                    ' task of creating the folder on remote device.    
                    CreateFolderStructure(remoteFolderPath, createParentDirectories)

                    ' Raise the CreateFolderCompleted event
                    RaiseEvent CreateFolderCompleted(Me, New CreateFolderCompletedEventArgs _
                                                    (remoteFolderPath, createParentDirectories, _
                                                     Nothing, False, Nothing))

                Catch ex As Exception

                    RaiseEvent CreateFolderCompleted(Me, New CreateFolderCompletedEventArgs _
                                                    (remoteFolderPath, createParentDirectories, _
                                                     ex, False, Nothing))

                    ' Raise the CreateFolderCompleted event
                    Throw New FTPException(FTPMessages.ErrorMsgCreateFolder, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Synchronous operation for getting the folder listing of a remote folder.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder on remote 
            ''' device.</param>
            ''' <returns>Returns the folder Listing in a XML Document format.
            ''' </returns>                      
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a GetFolderListing operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>      
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Function GetFolderListing(ByVal remoteFolderPath As String) As Xml.XmlDocument

                Dim folderListingDoc As Xml.XmlDocument = Nothing

                ' Verify if remoteFolderPath is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If


                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath.Length > 2 Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify if connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                RaiseEvent GetFolderListingBegin(Me, New GetFolderListingBeginEventArgs _
                                                 (remoteFolderPath, Nothing))

                ' Raise the GetFolderListingBegin event.
                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    ' Call GetFolderListingObject function which performs the 
                    ' actual task of getting the folder listing of folder on 
                    ' remote device.
                    folderListingDoc = GetFolderListingObject(remoteFolderPath)

                    ' Raise the GetFolderListingCompleted event.
                    RaiseEvent GetFolderListingCompleted(Me, New GetFolderListingCompletedEventArgs _
                                                         (remoteFolderPath, folderListingDoc, _
                                                          Nothing, False, Nothing))

                    Return folderListingDoc

                Catch ex As Exception

                    ' Raise the GetFolderListingCompleted event
                    RaiseEvent GetFolderListingCompleted(Me, New GetFolderListingCompletedEventArgs _
                                                         (remoteFolderPath, folderListingDoc, _
                                                         ex, False, Nothing))

                    Throw New FTPException(FTPMessages.ErrorMsgGetFolderListing, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try
            End Function

            ''' <summary>
            ''' Synchronous operation for setting the current directory on 
            ''' remote device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of remote folder to be 
            ''' set as current directory.</param>
            ''' <exception cref="FTPException">Thrown when 
            ''' an error occurs while performing a SetCurrentDirectory operation.
            ''' </exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception>     
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub SetCurrentDirectory(ByVal remoteFolderPath As String)

                ' Verify if remoteFolderPath is valid.
                If String.IsNullOrEmpty(remoteFolderPath) Then
                    Throw New ArgumentNullException(FTPMessages.RemoteFolderPath)
                End If

                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath.Length > 2 Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Verify connectionId is valid.
                If Me.connectionId Is Nothing Then
                    Throw New FTPException(FTPMessages.ErrorMessageNullConnId)
                End If

                ' Verify that the NetworkStream is set
                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Raise the SetCurrentDirectoryBegin event.
                RaiseEvent SetCurrentDirectoryBegin(Me, New SetCurrentDirectoryBeginEventArgs _
                                                    (remoteFolderPath, Nothing))

                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    ' Call SetCurrentDirectoryObject function which performs the 
                    ' actual task of setting the current directory on 
                    ' remote device.
                    SetCurrentDirectoryObject(remoteFolderPath)

                    ' Raise the SetCurrentDirectoryCompleted event
                    RaiseEvent SetCurrentDirectoryCompleted(Me, New SetCurrentDirectoryCompletedEventArgs _
                                                            (remoteFolderPath, Nothing, False, Nothing))

                Catch ex As Exception

                    ' Raise the SetCurrentDirectoryCompleted event
                    RaiseEvent SetCurrentDirectoryCompleted(Me, New SetCurrentDirectoryCompletedEventArgs _
                                                            (remoteFolderPath, ex, False, Nothing))

                    Throw New FTPException(FTPMessages.ErrorMsgSetCurrentDir, ex)

                Finally

                    ' Releases the exclusive lock on networkStream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Connects to the file transfer service.
            ''' </summary>   
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the Connect operation on remote device. 
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub Connect()

                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Obex packet for connect to a File transfer service
                Dim objectExchangeItemRequest As New ObjectExchangeItem(ObjectExchangeOpcode.Connect)

                ' Add a Obex Version Number fields.
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.ObexVersionNumber, New Byte() {16})

                ' Add a Flag fields
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Flags, New Byte() {0})

                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Target, New Byte() _
                                                    {249, 236, 123, 196, 149, 60, _
                                                    17, 210, 152, 78, 82, 84, _
                                                    0, 220, 158, 9})
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.MaxObexPacketLength, New Byte() {32, 0})

                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    ' Put the obex packet on te network stream
                    Me.netwrkStream.Write(objectExchangeItemRequest.GetByteStream(), 0, objectExchangeItemRequest.PacketSize)

                    ' Wait till data is available on  network stream
                    While Not Me.netwrkStream.DataAvailable
                        Continue While
                    End While

                    ' Sleep for 1 second till all data is put on stream.
                    Threading.Thread.Sleep(1000)

                    Dim responseStream As New IO.MemoryStream()

                    ' Read the response from stream
                    While Me.netwrkStream.DataAvailable
                        responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                    End While

                    Dim position As Long = responseStream.Seek(0, IO.SeekOrigin.Begin)
                    Dim objectExchangeItemResponse As New ObjectExchangeItem(responseStream)

                    If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Success OrElse _
                    objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.SuccessFinal Then

                        Dim headerTypes As ObjectExchangeHeaderType() = objectExchangeItemResponse.GetHeaderTypes()
                        For Each headerType As ObjectExchangeHeaderType In headerTypes

                            If headerType = ObjectExchangeHeaderType.ConnectionID Then

                                ' Store the connection id 
                                Me.connectionId = New Byte(objectExchangeItemResponse.GetHeader(headerType).Length - 1) {}
                                Me.connectionId = objectExchangeItemResponse.GetHeader(headerType)

                            End If

                            If headerType = ObjectExchangeHeaderType.MaxObexPacketLength Then

                                ' Store the max packet length received from remote device.
                                Me.maxPacketLength = ObjectExchangeHelper.FormatUInt16(BitConverter.ToUInt16 _
                                                                                       (objectExchangeItemResponse.GetHeader _
                                                                                        (headerType), 0))

                            End If

                        Next

                    Else
                        ObjectExchangeHelper.RaiseObjectExchangeError(objectExchangeItemResponse.Opcode)
                    End If

                    Return

                Finally

                    ' Release the lock on the networkstream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

            ''' <summary>
            ''' Disconnects from FTP service
            ''' </summary>        
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the Disconnect operation on remote device. 
            ''' </exception>
            ''' <exception cref="InvalidOperationException">Exception that is thrown when a 
            ''' method call is invalid for the object's current state.            
            ''' </exception>
            Public Sub Disconnect()

                If Me.netwrkStream Is Nothing Then
                    Throw New InvalidOperationException(FTPMessages.Error_NetworkStreamNotSet)
                End If

                ' Obex packet for disonnecting from service.
                Dim objectExchangeItemRequest As New ObjectExchangeItem(ObjectExchangeOpcode.Disconnect)

                ' Add ConnectionId header
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)

                ' Acquire an exclusive lock on the networkStream. 
                Threading.Monitor.Enter(Me.netwrkStream)

                Try
                    ' Puts the request on network stream
                    Me.netwrkStream.Write(objectExchangeItemRequest.GetByteStream(), 0, objectExchangeItemRequest.PacketSize)

                    ' Wait till data is available on  network stream
                    While Not Me.netwrkStream.DataAvailable
                        Continue While
                    End While

                    Dim responseStream As New IO.MemoryStream()

                    ' Sleep for 1 second till all data is put on stream.
                    Threading.Thread.Sleep(1000)

                    ' Read response from stream
                    While Me.netwrkStream.DataAvailable
                        responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                    End While

                    Dim position As Long = responseStream.Seek(0, IO.SeekOrigin.Begin)
                    Dim objectExchangeItemResponse As New ObjectExchangeItem(responseStream)

                    ' Verify the response code
                    If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Success _
                    OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.SuccessFinal Then
                        Return
                    Else
                        ObjectExchangeHelper.RaiseObjectExchangeError(objectExchangeItemResponse.Opcode)

                    End If

                Finally

                    ' Release the lock on the networkstream
                    Threading.Monitor.Exit(Me.netwrkStream)

                End Try

            End Sub

#End Region

#End Region

#Region "Private Functions"

            ''' <summary>
            ''' Initializes FTPManager object.
            ''' </summary>
            Private Sub InitializeFTPManager()

                With Me
                    ' Initialize the list used to maintain pending asynchronous 
                    ' FTPRequest.
                    .requestQueue = New List(Of FTPRequest)()

                    ' Initialize the DoWork event handler of BackgroundWorker.
                    .asyncOperationHandler = New ComponentModel.BackgroundWorker()

                    ' Initializes the RunWorkerCompleted event handler of 
                    ' BackgroundWorker.
                    .asyncOperationHandler.WorkerSupportsCancellation = True
                End With

            End Sub

            ''' <summary>
            ''' Sets the specified folder as current folder on remote device.
            ''' </summary>
            ''' <param name="remoteFolderName">Name of the folder to be set as 
            ''' current folder on remote device.</param>
            ''' <returns>Returns true if folder set as current folder else returns
            ''' false.</returns>                              
            Private Function SetCurrentFolder(ByVal remoteFolderName As String) As Boolean

                Try
                    Dim objectExchangeItemRequest As ObjectExchangeItem = Nothing
                    Dim responseStream As IO.MemoryStream = Nothing
                    Dim objectExchangeItemResponse As ObjectExchangeItem = Nothing

                    ' Obex packet for setting current folder to root folder.
                    If remoteFolderName.Equals(String.Empty) Then


                        ' Initiailize the objectExchangeItem object with an
                        ' opcode of SetPath
                        objectExchangeItemRequest = New ObjectExchangeItem(ObjectExchangeOpcode.SetPath)
                        With objectExchangeItemRequest
                            ' Add flags field
                            .AddHeader(ObjectExchangeHeaderType.Flags, New Byte() {2})

                            ' Adds Constants field.
                            .AddHeader(ObjectExchangeHeaderType.Constants, New Byte() {0})

                            ' Adds connectionId header
                            .AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)

                            ' Adds name header
                            .AddHeader(ObjectExchangeHeaderType.Name, New Byte() {})
                        End With

                    ElseIf remoteFolderName.Equals(FTPMessages.ParentFolder) Then

                        ' Obex packet for setting current folder to parent folder.
                        ' Initiailize the objectExchangeItem object with an opcode 
                        ' of SetPath
                        objectExchangeItemRequest = New ObjectExchangeItem(ObjectExchangeOpcode.SetPath)
                        With objectExchangeItemRequest
                            ' Add flags field
                            .AddHeader(ObjectExchangeHeaderType.Flags, New Byte() {3})

                            ' Adds Constants field.
                            .AddHeader(ObjectExchangeHeaderType.Constants, New Byte() {0})

                            ' Adds connectionId header
                            .AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)
                        End With

                    ElseIf Not remoteFolderName.Equals(FTPMessages.CurrentFolder) Then

                        ' obex packet for setting current folder to a child folder.
                        ' Initiailize the objectExchangeItem object with an opcode 
                        ' of SetPath
                        objectExchangeItemRequest = New ObjectExchangeItem(ObjectExchangeOpcode.SetPath)

                        With objectExchangeItemRequest
                            ' Add flags field
                            .AddHeader(ObjectExchangeHeaderType.Flags, New Byte() {2})

                            ' Adds Constants field.
                            .AddHeader(ObjectExchangeHeaderType.Constants, New Byte() {0})

                            ' Adds connectionId header
                            .AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)

                            ' Adds name header
                            objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Name, remoteFolderName + "\0")
                        End With

                    End If

                    ' Put request on network stream.
                    netwrkStream.Write(objectExchangeItemRequest.GetByteStream(), 0, _
                                       objectExchangeItemRequest.PacketSize)

                    ' Wait for response
                    While Not Me.netwrkStream.DataAvailable
                        Continue While
                    End While

                    responseStream = New IO.MemoryStream()
                    ' Sleep for 1 second till all data is put on stream.
                    Threading.Thread.Sleep(1000)

                    ' Read response from network stream.
                    While Me.netwrkStream.DataAvailable
                        responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                    End While

                    Dim position As Long = responseStream.Seek(0, IO.SeekOrigin.Begin)
                    objectExchangeItemResponse = New ObjectExchangeItem(responseStream)

                    If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Success _
                    OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.SuccessFinal Then
                        Return True
                    Else
                        Return False

                    End If

                Catch
                    ' In an error occurs return false.
                    Return False

                End Try

            End Function

            ''' <summary>
            ''' Gets the folder listing of the current folder.
            ''' </summary>
            ''' <returns>Returns a XMLDocument containing the folder listing in
            ''' XML Format.</returns> 
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>            
            Private Function GetCurrentFolderListingObject() As Xml.XmlDocument

                Dim fileData As Byte() = Nothing
                Dim fileStream As New IO.MemoryStream()
                Dim fileWriter As New IO.BinaryWriter(fileStream)
                Dim folderListingDocument As New Xml.XmlDocument()
                Dim objectExchangeItemRequest As ObjectExchangeItem = Nothing
                Dim responseStream As IO.MemoryStream = Nothing
                Dim objectExchangeItemResponse As ObjectExchangeItem = Nothing
                Dim continueGet As Boolean = False

                ' Obex packet for Getting the FolderListing of remote 
                ' folder.
                Do
                    ' Initiailize the objectExchangeItem object with an
                    ' opcode of Get
                    objectExchangeItemRequest = New ObjectExchangeItem(ObjectExchangeOpcode.GetFinal)

                    ' Add these headers only in the first request of Get
                    If Not continueGet Then

                        With objectExchangeItemRequest
                            ' Add a connectionId header
                            .AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)

                            ' Add a name header
                            .AddHeader(ObjectExchangeHeaderType.Name, New Byte() {})

                            ' Add a type header
                            .AddHeader(ObjectExchangeHeaderType.Type, FTPMessages.FolderListingFormat)
                        End With

                    End If

                    ' Put the request on the network stream
                    Me.netwrkStream.Write(objectExchangeItemRequest.GetByteStream(), 0, _
                                          objectExchangeItemRequest.PacketSize)

                    ' Waits for response
                    While Not Me.netwrkStream.DataAvailable
                        Continue While
                    End While

                    responseStream = New IO.MemoryStream()

                    ' Sleep for 1 second till all data is put on stream.
                    Threading.Thread.Sleep(1000)

                    ' Reads the response from network stream.
                    While Me.netwrkStream.DataAvailable
                        responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                    End While

                    Dim position As Long = responseStream.Seek(0, IO.SeekOrigin.Begin)
                    objectExchangeItemResponse = New ObjectExchangeItem(responseStream)

                    ' Verify the response code.
                    If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Continued _
                    OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.ContinueFinal Then

                        If objectExchangeItemResponse.HeaderTypeExists(ObjectExchangeHeaderType.Body) Then
                            fileWriter.Write(objectExchangeItemResponse.GetHeader(ObjectExchangeHeaderType.Body))
                        End If
                        continueGet = True

                    End If

                    If (objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Success _
                        OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.SuccessFinal) Then

                        If objectExchangeItemResponse.HeaderTypeExists(ObjectExchangeHeaderType.EndOfBody) Then
                            fileWriter.Write(objectExchangeItemResponse.GetHeader(ObjectExchangeHeaderType.EndOfBody))
                        End If

                        fileData = fileStream.ToArray()
                        fileWriter.Close()

                        Dim folderContents As String = Encoding.ASCII.GetString(fileData)

                        If folderContents.Contains(FTPMessages.FolderListingTag) Then

                            ' Get the position of FolderListing tag in the 
                            ' folderContents string
                            Dim iPos As Integer = folderContents.IndexOf(FTPMessages.FolderListingTag)

                            ' Extracts folderListing string.
                            Dim folderListing As String = folderContents.Substring(iPos)

                            ' Loads the xml document with the folderListing document.
                            folderListingDocument.LoadXml(folderListing)

                        End If
                        continueGet = False

                    Else

                        ObjectExchangeHelper.RaiseObjectExchangeError(objectExchangeItemResponse.Opcode)
                        ' Raise the error

                    End If

                Loop While continueGet

                Return folderListingDocument

            End Function

            ''' <summary>
            ''' Deletes a folder and its sub-folders.This function recursively
            ''' deletes the folders along with its contents. 
            ''' </summary>
            ''' <param name="remoteFolderName">Name of the folder to be deleted.
            ''' </param>
            ''' <exception cref="ObjectExchangeException">Throws an ObjectExchangeException
            ''' indicating that an error has occured while performing the 
            ''' operation on remote device. </exception>           
            Private Sub DeleteWithSubFolders(ByVal remoteFolderName As String)

                ' Sets the current folder.
                If SetCurrentFolder(remoteFolderName) Then
                    Dim doc As Xml.XmlDocument = Nothing

                    ' Gets the folder listing of current folder.
                    doc = GetCurrentFolderListingObject()

                    If doc IsNot Nothing Then
                        ' Get list of folders
                        Dim folderList As Xml.XmlNodeList = doc.GetElementsByTagName(FTPMessages.Folder)

                        ' Get list of files
                        Dim fileList As Xml.XmlNodeList = doc.GetElementsByTagName(FTPMessages.File)

                        ' Delete all files in the fileList
                        If fileList IsNot Nothing AndAlso fileList.Count <> 0 Then

                            For Each node As Xml.XmlNode In fileList

                                Dim attrCollection As Xml.XmlAttributeCollection = node.Attributes

                                If attrCollection IsNot Nothing AndAlso attrCollection.Count <> 0 Then

                                    ' Retrieve the name of the file.
                                    Dim attrNode As Xml.XmlNode = attrCollection.GetNamedItem(FTPMessages.Name)
                                    ' Delete the file

                                    If attrNode IsNot Nothing Then
                                        DeleteObject(attrNode.Value)
                                    End If

                                End If

                            Next

                        End If

                        ' Delete all folders in the folderList.
                        If folderList IsNot Nothing AndAlso folderList.Count <> 0 Then

                            If folderList.Count > 0 Then

                                For Each node As Xml.XmlNode In folderList

                                    Dim attrCollection As Xml.XmlAttributeCollection = node.Attributes
                                    If attrCollection IsNot Nothing AndAlso attrCollection.Count <> 0 Then

                                        ' Retrieve the name of the folder.
                                        Dim attrNode As Xml.XmlNode = attrCollection.GetNamedItem(FTPMessages.Name)

                                        If attrNode IsNot Nothing Then

                                            ' Recursive call. Delete the folder.
                                            DeleteWithSubFolders(attrNode.Value)

                                        End If

                                    End If

                                Next

                            End If

                        End If

                        ' If empty folder then delete it.
                        If SetCurrentFolder(FTPMessages.ParentFolder) Then
                            DeleteObject(remoteFolderName)
                        End If

                    End If

                End If

            End Sub

            ''' <summary>
            ''' Traverses the file path and deletes the file.
            ''' </summary>
            ''' <param name="remoteFilePath">Location of file on remote device.</param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception> 
            ''' <exception cref="ArgumentException">Thrown when 
            ''' one of the arguments provided to the method is not valid.
            ''' </exception>
            Private Sub DeleteFileObject(ByVal remoteFilePath As String)

                Dim fileName As String = String.Empty
                ' Split remoteFilePath on Directory Seperator.
                Dim delimeters() As Char = {"\"c}
                Dim folders() As String = remoteFilePath.Split(delimeters)
                Dim bRoot As Boolean = False

                ' Indicates the first directory is root folder.  
                ' Set the flag bRoot to true.
                If folders(0) = String.Empty Then
                    bRoot = True
                End If

                For i As Integer = 0 To folders.Length - 2

                    ' Traverse the folder hierarchy. Set the current 
                    ' directory on remote device.
                    ' Ignore further 
                    If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                        Continue For
                    End If

                    If Not SetCurrentFolder(folders(i)) Then
                        Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, _
                                                    FTPMessages.RemoteFilePath)
                    End If

                Next

                fileName = folders(folders.Length - 1)

                If String.IsNullOrEmpty(fileName) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, _
                                                FTPMessages.RemoteFilePath)
                End If

                ' Delets the file.
                DeleteObject(fileName)

            End Sub

            ''' <summary>
            ''' Deletes a file/folder from remote device.
            ''' </summary>
            ''' <param name="objectName">Name of the object to be deleted.
            ''' </param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the operation on remote device.</exception>                       
            Private Sub DeleteObject(ByVal objectName As String)

                Dim objectExchangeItemRequest As ObjectExchangeItem = Nothing
                Dim responseStream As IO.MemoryStream = Nothing
                Dim objectExchangeItemResponse As ObjectExchangeItem = Nothing

                ' Initialize the objectExchangeItem with an opcode of Put
                objectExchangeItemRequest = New ObjectExchangeItem(ObjectExchangeOpcode.PutFinal)

                ' Add connectionId header
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.ConnectionID, _
                                                    Me.connectionId)

                ' Add Name header
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Name, objectName + "\0")

                ' Puts the request on network stream.
                Me.netwrkStream.Write(objectExchangeItemRequest.GetByteStream(), 0, _
                                      objectExchangeItemRequest.PacketSize)

                ' Waits for response from the remote device.
                While Not Me.netwrkStream.DataAvailable
                    Continue While
                End While

                ' Sleep for 1 second till all data is put on stream.
                Threading.Thread.Sleep(1000)

                ' Reads response from stream.
                responseStream = New IO.MemoryStream()
                While Me.netwrkStream.DataAvailable
                    responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                End While

                Dim position As Long = responseStream.Seek(0, IO.SeekOrigin.Begin)

                objectExchangeItemResponse = New ObjectExchangeItem(responseStream)

                ' Verify the response code.
                If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Success _
                OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.SuccessFinal Then
                    Return
                Else
                    ObjectExchangeHelper.RaiseObjectExchangeError(objectExchangeItemResponse.Opcode)
                End If

            End Sub

            ''' <summary>
            ''' Pushes a file on to remote device.
            ''' </summary>
            ''' <param name="remoteFilePath">Location of the file to be pushed 
            ''' on to remote device.</param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the operation on remote device.</exception>  
            Private Sub SendFileObject(ByVal remoteFilePath As String)
                ' Retrieve the file name 
                Dim fileName As String = IO.Path.GetFileName(remoteFilePath)

                ' Extract contents of file.
                Dim fileContents As New IO.MemoryStream(IO.File.ReadAllBytes(remoteFilePath))


                ' Calls the SendFileObject overload
                SendFileObject(fileContents, fileName)

            End Sub

            ''' <summary>
            ''' Pushes a file to remote device.
            ''' </summary>
            ''' <param name="fileContents">MemoryStream containing the file 
            ''' contents.</param>
            ''' <param name="fileName">Name of file to be created on remote 
            ''' device.</param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            Private Sub SendFileObject(ByVal fileContents As IO.MemoryStream, ByVal fileName As String)

                Dim fileContent() As Byte = fileContents.ToArray()

                Dim fileStream As New IO.MemoryStream(fileContent)
                Dim fileReader As New IO.BinaryReader(fileStream)

                ' Create the Put request.
                Dim putRequestPackets As New List(Of ObjectExchangeItem)()

                ' Initialize a objectExchangeItem with the Put opcode.
                Dim objectExchangeItemRequest As New ObjectExchangeItem(ObjectExchangeOpcode.Put)

                ' Add name header
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Name, fileName)

                ' Add length header
                objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Length, _
                                                    BitConverter.GetBytes(ObjectExchangeHelper.FormatUInt32 _
                                                                          (Convert.ToUInt32(fileContent.Length))))


                Dim bytesLeftToRead As Long = fileStream.Length

                ' Object is large. So split the Object into packets.
                ' 1st packet.
                If (objectExchangeItemRequest.PacketSize + bytesLeftToRead + 3) > Me.maxPacketLength Then

                    Dim noOfBytesToRead As Integer = Me.maxPacketLength - objectExchangeItemRequest.PacketSize - 3

                    ' Add Body Header
                    objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Body, _
                                                        fileReader.ReadBytes(noOfBytesToRead))

                    bytesLeftToRead -= noOfBytesToRead
                    putRequestPackets.Add(objectExchangeItemRequest)

                    While bytesLeftToRead > 0

                        objectExchangeItemRequest = New ObjectExchangeItem(ObjectExchangeOpcode.Put)
                        If bytesLeftToRead > (Me.maxPacketLength - objectExchangeItemRequest.PacketSize - 3) Then
                            noOfBytesToRead = Me.maxPacketLength - objectExchangeItemRequest.PacketSize - 3

                            ' Add Body Header
                            objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.Body, _
                                                                fileReader.ReadBytes(noOfBytesToRead))
                        Else
                            ' Last packet.
                            objectExchangeItemRequest.Opcode = ObjectExchangeOpcode.PutFinal

                            noOfBytesToRead = CInt(bytesLeftToRead)

                            ' Add an EndOfBody Header
                            objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.EndOfBody, _
                                                                fileReader.ReadBytes(noOfBytesToRead))
                        End If

                        bytesLeftToRead -= noOfBytesToRead
                        ' Add packet to list
                        putRequestPackets.Add(objectExchangeItemRequest)
                    End While

                Else

                    ' Object fits in 1 packet.
                    objectExchangeItemRequest.Opcode = ObjectExchangeOpcode.PutFinal

                    objectExchangeItemRequest.AddHeader(ObjectExchangeHeaderType.EndOfBody, _
                                                        fileReader.ReadBytes(CInt(bytesLeftToRead)))

                    ' Add packet to queue
                    putRequestPackets.Add(objectExchangeItemRequest)

                End If

                For packetNo As Integer = 0 To putRequestPackets.Count - 1

                    ' loop through the packets in the list and put them
                    ' on network stream one by one.
                    Dim putRequestBytes() As Byte = putRequestPackets(packetNo).GetByteStream()
                    Dim putResponseStream As New IO.MemoryStream()

                    Try
                        ' Send the Put request.
                        Me.netwrkStream.Write(putRequestBytes, 0, putRequestBytes.Length)

                        ' Sleep for 1 second till all data is put on stream.
                        Threading.Thread.Sleep(1000)

                        While Not Me.netwrkStream.DataAvailable
                            Continue While
                        End While

                        ' Read the response.
                        While Me.netwrkStream.DataAvailable
                            putResponseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                        End While

                        putResponseStream.Seek(0, IO.SeekOrigin.Begin)

                    Catch ioEx As IO.IOException

                        Throw New ObjectExchangeException(ObjectExchangeErrorType.StreamError, _
                                                          FTPMessages.ErrorMsgWritetoStream, ioEx)

                    Catch objEx As ObjectDisposedException

                        Throw New ObjectExchangeException(ObjectExchangeErrorType.StreamError, _
                                                          FTPMessages.ErrorMsgWritetoStream, objEx)
                    End Try

                    Dim objectExchangeItemResponse As New ObjectExchangeItem(putResponseStream)

                    ' Verify the response code
                    If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Success _
                    OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.SuccessFinal Then
                        Return
                    End If

                    If objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.Continued _
                    OrElse objectExchangeItemResponse.Opcode = ObjectExchangeOpcode.ContinueFinal Then
                        Continue For
                    Else
                        ObjectExchangeHelper.RaiseObjectExchangeError(objectExchangeItemResponse.Opcode)

                    End If

                Next

            End Sub

            ''' <summary>
            ''' Pushes a folder on remote device.
            ''' </summary>
            ''' <param name="localFolderPath">Location of folder to be pushed 
            ''' on to remote device </param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            Private Sub SendFolderObject(ByVal localFolderPath As String)

                Dim directoryObject As New IO.DirectoryInfo(localFolderPath)

                ' Create folder on remote device.
                CreateFolderObject(directoryObject.Name)

                ' Get a list of files present in the directory
                Dim files() As IO.FileInfo = directoryObject.GetFiles()

                ' Pushes a each file on to remote device.
                For Each fileInfo As IO.FileInfo In files

                    ' SendFileObject(fileInfo.DirectoryName +
                    '               "\\" +
                    '               fileInfo.ToString());
                    SendFileObject(fileInfo.FullName)

                Next

                ' Get a list of the sub-directories in the directory.
                Dim folders() As IO.DirectoryInfo = directoryObject.GetDirectories()

                ' Pushes each folder on to remote device.
                For Each directoryInfo As IO.DirectoryInfo In folders

                    ' Calls the function recursively
                    SendFolderObject(directoryInfo.FullName)
                    ' Set the current folder on remote device to that of the parent.
                    SetCurrentFolder(FTPMessages.ParentFolder)

                Next

            End Sub

            ''' <summary>
            ''' Creates the folder structure and transfers 
            ''' contents of the pulled folder on local device.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder to be pulled 
            ''' from remote device. </param>
            ''' <param name="localFolderPath">Location on local device where 
            ''' the pulled folder will be created.</param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            Private Sub GetFolderObject(ByVal remoteFolderPath As String, ByVal localFolderPath As String)

                ' Split the folderPath on Directory Seperator.
                Dim delimiters() As Char = {"\"c}
                Dim folders() As String = remoteFolderPath.Split(delimiters)
                Dim bRoot As Boolean = False

                ' Indicates the first directory is root folder.  
                ' Set the flag bRoot to true.
                If folders(0) = String.Empty Then
                    bRoot = True
                End If

                For i As Integer = 0 To folders.Length - 2

                    ' Traverse the folder hierarchy. Set the current 
                    ' directory on remote device.
                    ' Ignore any further occurences of empty strings.
                    If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                        Continue For
                    End If

                    If Not SetCurrentFolder(folders(i)) Then
                        Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFolderPath, _
                                                    FTPMessages.RemoteFolderPath)

                    End If

                Next

                Dim folderName As String = folders(folders.Length - 1)

                If String.IsNullOrEmpty(folderName) Then
                    Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFolderPath, _
                                                FTPMessages.RemoteFolderPath)
                End If

                ' Set the current folder on remote device
                If SetCurrentFolder(folderName) Then

                    ' Create the same folder on the local device.
                    Dim dir As IO.DirectoryInfo = IO.Directory.CreateDirectory(localFolderPath + "\" + folderName)
                    ' Append the folderName to the localFolderPath
                    localFolderPath = localFolderPath + "\" + folderName
                    Dim doc As Xml.XmlDocument = Nothing
                    ' Get FolderListing of the current folder
                    doc = GetCurrentFolderListingObject()

                    If doc IsNot Nothing Then

                        ' Get a list of folders
                        Dim folderList As Xml.XmlNodeList = doc.GetElementsByTagName(FTPMessages.Folder)
                        ' Get a list of files
                        Dim fileList As Xml.XmlNodeList = doc.GetElementsByTagName(FTPMessages.File)

                        ' For each file in the list get its contents and then create a file on local
                        ' device with received file content.

                        If fileList IsNot Nothing AndAlso fileList.Count <> 0 Then

                            For Each node As Xml.XmlNode In fileList

                                Dim attrCollection As Xml.XmlAttributeCollection = node.Attributes
                                If attrCollection IsNot Nothing AndAlso attrCollection.Count <> 0 Then

                                    Dim attrNode As Xml.XmlNode = attrCollection.GetNamedItem(FTPMessages.Name)
                                    If attrNode IsNot Nothing Then

                                        ' Get the file contents
                                        Dim fileData() As Byte = GetFileObject(attrNode.Value)
                                        ' Write to the local file.
                                        IO.File.WriteAllBytes(localFolderPath + "\" + attrNode.Value, fileData)

                                    End If

                                End If

                            Next

                        End If

                        ' For each folder in the list create a folder on local device.
                        If folderList IsNot Nothing AndAlso folderList.Count <> 0 Then

                            For Each node As Xml.XmlNode In folderList

                                Dim attrCollection As Xml.XmlAttributeCollection = node.Attributes
                                If attrCollection IsNot Nothing AndAlso attrCollection.Count <> 0 Then

                                    Dim attrNode As Xml.XmlNode = attrCollection.GetNamedItem(FTPMessages.Name)
                                    If attrNode IsNot Nothing Then

                                        ' Get folder object
                                        GetFolderObject(attrNode.Value, localFolderPath + "\")
                                        ' Set Parent folder
                                        SetCurrentFolder(FTPMessages.ParentFolder)

                                    End If

                                End If

                            Next

                        End If

                    End If

                End If

            End Sub

            ''' <summary>
            ''' Pulls the specified file from the device.
            ''' </summary>
            ''' <param name="remoteFilePath">Location of the file to be pulled
            ''' from remote device.</param>
            ''' <returns>Returns a byte array containing the file data.</returns>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            Private Function GetFileObject(ByVal remoteFilePath As String) As Byte()

                Dim fileData() As Byte = {}
                Dim receivedLengthOfFile As UInteger = 0
                Dim fileStream As New IO.MemoryStream()
                Dim fileWriter As New IO.BinaryWriter(fileStream)
                ' Split the folderPath on Directory Seperator. 
                Dim delimeters() As Char = {"\"c}
                Dim folders() As String = remoteFilePath.Split(delimeters)
                Dim bRoot As Boolean = False

                ' Indicates the first directory is root folder.  
                ' Set the flag bRoot to true.
                If folders(0) = String.Empty Then
                    bRoot = True
                End If

                For i As Integer = 0 To folders.Length - 2

                    ' Traverse the folder hierarchy. Set the current 
                    ' directory on remote device.
                    ' Ignore any further occurences of empty strings.
                    If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                        Continue For
                    End If

                    If Not SetCurrentFolder(folders(i)) Then
                        Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFilePath, _
                                                    FTPMessages.RemoteFilePath)

                    End If

                Next

                Dim fileName As String = folders(folders.Length - 1)

                If String.IsNullOrEmpty(fileName) Then
                    Throw New ArgumentException(FTPMessages.RemoteFilePath, _
                                                FTPMessages.RemoteFilePath)
                End If

                Dim continueGet As Boolean = False

                Do
                    ' Create the Get Default Object request.
                    Dim obexReq As New ObjectExchangeItem(ObjectExchangeOpcode.GetFinal)
                    If Not continueGet Then

                        ' Add connectionId header
                        obexReq.AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)

                        ' Add Name header
                        obexReq.AddHeader(ObjectExchangeHeaderType.Name, fileName)

                    End If

                    Dim responseStream As New IO.MemoryStream()

                    Try

                        ' Send the Get request.
                        Me.netwrkStream.Write(obexReq.GetByteStream(), 0, obexReq.PacketSize)

                        ' Sleep for 1 second till all data is put on stream.                        
                        Threading.Thread.Sleep(1000)

                        While Not Me.netwrkStream.DataAvailable
                            Continue While
                        End While

                        ' Read the response.
                        While Me.netwrkStream.DataAvailable
                            responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                        End While

                        responseStream.Seek(0, IO.SeekOrigin.Begin)

                    Catch ioEx As IO.IOException
                        Throw New ObjectExchangeException(ObjectExchangeErrorType.StreamError, _
                                                          FTPMessages.ErrorMsgWritetoStream, ioEx)

                    Catch objEx As ObjectDisposedException
                        Throw New ObjectExchangeException(ObjectExchangeErrorType.StreamError, _
                                                          FTPMessages.ErrorMsgWritetoStream, objEx)

                    End Try

                    Dim obexRes As New ObjectExchangeItem(responseStream)
                    If obexRes.Opcode = ObjectExchangeOpcode.Continued _
                    OrElse obexRes.Opcode = ObjectExchangeOpcode.ContinueFinal Then

                        If obexRes.HeaderTypeExists(ObjectExchangeHeaderType.Length) Then
                            receivedLengthOfFile = CUInt(ObjectExchangeHelper.FormatUInt32(BitConverter.ToUInt32 _
                                                                                           (obexRes.GetHeader _
                                                                                            (ObjectExchangeHeaderType.Length), 0)))
                        End If

                        If obexRes.HeaderTypeExists(ObjectExchangeHeaderType.Body) Then
                            fileWriter.Write(obexRes.GetHeader(ObjectExchangeHeaderType.Body))
                        End If

                        continueGet = True

                    End If

                    If obexRes.Opcode = ObjectExchangeOpcode.Success _
                    OrElse obexRes.Opcode = ObjectExchangeOpcode.SuccessFinal Then

                        If obexRes.HeaderTypeExists(ObjectExchangeHeaderType.EndOfBody) Then
                            fileWriter.Write(obexRes.GetHeader(ObjectExchangeHeaderType.EndOfBody))
                        End If

                        ' Get the file contents.
                        fileData = fileStream.ToArray()
                        fileWriter.Close()

                        If receivedLengthOfFile > 0 AndAlso fileData.Length <> receivedLengthOfFile Then
                            Throw New ObjectExchangeException(ObjectExchangeErrorType.StreamError, _
                                                              FTPMessages.ErrorMsgIncompleteFile)
                        End If

                        continueGet = False
                    Else

                        ObjectExchangeHelper.RaiseObjectExchangeError(obexRes.Opcode)

                    End If

                Loop While continueGet

                Return fileData

            End Function

            ''' <summary>
            ''' Traverses the remoteFolderPath and creates the folder on the 
            ''' remote device.            
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of the folder to be 
            ''' created</param>        
            ''' <param name="createParentDirectories">Flag indicating if 
            ''' non-existing parent directories have to be created.</param>  
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            Private Sub CreateFolderStructure(ByVal remoteFolderPath As String, _
                                               ByVal createParentDirectories As Boolean)

                Dim directoryExists As Boolean = False
                ' Split the folderPath on Directory Seperator.

                Dim delimeters() As Char = {"\"c}
                Dim folders() As String = remoteFolderPath.Split(delimeters)

                ' Verifies if all folders in remoteFolderPath exist.
                Dim folderName As String = folders(folders.Length - 1)
                Dim bRoot As Boolean = False

                ' Indicates the first directory is root folder.  
                ' Set the flag bRoot to true.
                If folders(0) = String.Empty Then
                    bRoot = True
                End If

                For i As Integer = 0 To folders.Length - 2

                    ' Traverse the folder hierarchy. Set the current 
                    ' directory on remote device.
                    ' Ignore any further occurences of empty strings.
                    If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                        Continue For
                    End If

                    directoryExists = SetCurrentFolder(folders(i))

                    ' if folder doesn't exist and createParentDirectories 
                    ' flag is true then create folder.

                    If Not directoryExists Then

                        If createParentDirectories Then
                            CreateFolderObject(folders(i))
                        Else
                            ' The remote folder path is invalid.
                            Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFolderPath, _
                                                        FTPMessages.RemoteFolderPath)
                        End If

                    Else

                        Continue For

                    End If

                Next

                ' Create the folder.
                CreateFolderObject(folderName)
            End Sub

            ''' <summary>
            ''' Creates the folder on remote device.
            ''' </summary>
            ''' <param name="remoteFolderName">Name of the folder to be 
            ''' created.</param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            Private Sub CreateFolderObject(ByVal remoteFolderName As String)

                Dim obexReq As ObjectExchangeItem = Nothing
                Dim responseStream As IO.MemoryStream = Nothing
                Dim obexRes As ObjectExchangeItem = Nothing

                ' Obex packet for create directory request
                obexReq = New ObjectExchangeItem(ObjectExchangeOpcode.SetPath)
                ' Add flags field
                obexReq.AddHeader(ObjectExchangeHeaderType.Flags, New Byte() {0})

                ' Add constants field
                obexReq.AddHeader(ObjectExchangeHeaderType.Constants, New Byte() {0})

                ' Add connectionId header
                obexReq.AddHeader(ObjectExchangeHeaderType.ConnectionID, Me.connectionId)

                ' Add name header
                obexReq.AddHeader(ObjectExchangeHeaderType.Name, remoteFolderName + "\0")


                ' Puts request on network stream
                Me.netwrkStream.Write(obexReq.GetByteStream(), 0, obexReq.PacketSize)

                ' Waits for response
                While Not Me.netwrkStream.DataAvailable
                    Continue While
                End While

                ' Sleep for 1 second till all data is put on stream.                        
                Threading.Thread.Sleep(1000)

                ' Reads response
                responseStream = New IO.MemoryStream()
                While Me.netwrkStream.DataAvailable
                    responseStream.WriteByte(CByte(Me.netwrkStream.ReadByte()))
                End While

                Dim position As Long = responseStream.Seek(0, IO.SeekOrigin.Begin)
                obexRes = New ObjectExchangeItem(responseStream)

                If obexRes.Opcode = ObjectExchangeOpcode.Success _
                OrElse obexRes.Opcode = ObjectExchangeOpcode.SuccessFinal Then
                    Return
                Else
                    ObjectExchangeHelper.RaiseObjectExchangeError(obexRes.Opcode)
                End If

            End Sub

            ''' <summary>
            ''' Traverses the folder path and gets the folder listing.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of the folder 
            ''' on remote device.</param>
            ''' <returns>XmlDocument containing the folder listing.</returns>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            Private Function GetFolderListingObject(ByVal remoteFolderPath As String) As Xml.XmlDocument

                If remoteFolderPath.Equals("\") Then
                    SetCurrentFolder(String.Empty)
                Else

                    ' Split the folderPath on Directory Seperator.
                    Dim delimiters() As Char = {"\"c}
                    Dim folders() As String = remoteFolderPath.Split(delimiters)
                    Dim bRoot As Boolean = False

                    ' Verify if the first string is a root folder
                    If folders(0) = String.Empty Then
                        bRoot = True
                    End If

                    For i As Integer = 0 To folders.Length - 1

                        ' Traverse the folder hierarchy. Set the current 
                        ' directory on remote device.
                        ' Ignore any further occurences of empty strings.
                        If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                            Continue For
                        End If

                        If Not SetCurrentFolder(folders(i)) Then
                            Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFolderPath, _
                                                        FTPMessages.RemoteFolderPath)
                        End If

                    Next

                End If

                ' Get the current listing of the folder.
                Return GetCurrentFolderListingObject()

            End Function

            ''' <summary>
            ''' Traverses the remoteFolderPath and Sets the current directory.
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of the folder to be set
            ''' as current directory</param>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the File Transfer operation on remote device.</exception>
            ''' <exception cref="ArgumentException">Thrown when 
            ''' when one of the arguments provided to the method is not valid.
            ''' </exception>
            Private Sub SetCurrentDirectoryObject(ByVal remoteFolderPath As String)

                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath.Length > 2 Then
                    remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                'Split the folderPath on Directory Seperator.
                Dim delimeters() As Char = {"\"c}
                Dim folders() As String = remoteFolderPath.Split(delimeters)

                ' Set to root folder
                If remoteFolderPath.Equals("\") Then
                    SetCurrentFolder(String.Empty)
                Else

                    Dim bRoot As Boolean = False

                    ' Indicates the first directory is root folder.  
                    ' Set the flag bRoot to true.
                    If folders(0) = String.Empty Then
                        bRoot = True
                    End If

                    For i As Integer = 0 To folders.Length - 1

                        ' Traverse the folder hierarchy. Set the current 
                        ' directory on remote device.
                        ' Ignore any further occurences of empty strings.
                        If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                            Continue For
                        End If

                        If Not SetCurrentFolder(folders(i)) Then
                            Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFolderPath, _
                                                        FTPMessages.RemoteFolderPath)
                        End If

                    Next

                End If

            End Sub

            ''' <summary>
            ''' Traverses the remoteFolderPath and deletes the folder
            ''' </summary>
            ''' <param name="remoteFolderPath">Location of folder on remote 
            ''' device. </param>
            ''' <param name="deleteSubDirectories">Flag indicating if sub-directories 
            ''' have to be deleted.</param>
            ''' <exception cref="ArgumentException">Thrown when one of the arguments 
            ''' provided to the method is not valid.. </exception>
            ''' <exception cref="ObjectExchangeException">Thrown when an error has occured 
            ''' while performing the operation on remote device. </exception>            
            Private Sub DeleteFolderObject(ByVal remoteFolderPath As String, ByVal deleteSubDirectories As Boolean)

                Dim folderName As String = String.Empty

                If remoteFolderPath.EndsWith("\") AndAlso remoteFolderPath.Length > 2 Then
                    remoteFolderPath = remoteFolderPath.Remove(remoteFolderPath.Length - 1)
                End If

                ' Split the folderPath on Directory Seperator.
                Dim delimeters() As Char = {"\"c}
                Dim folders() As String = remoteFolderPath.Split(delimeters)
                Dim bRoot As Boolean = False

                ' Indicates the first directory is root folder.  
                ' Set the flag bRoot to true.
                If folders(0) = String.Empty Then
                    bRoot = True
                End If

                For i As Integer = 0 To folders.Length - 2

                    ' Traverse the folder hierarchy. Set the current 
                    ' directory on remote device.
                    ' Ignore any further occurences of empty strings.
                    If folders(i) = String.Empty AndAlso i <> 0 AndAlso bRoot Then
                        Continue For
                    End If

                    If Not SetCurrentFolder(folders(i)) Then
                        Throw New ArgumentException(FTPMessages.ErrorMsgInvalidRemoteFolderPath, _
                                                    FTPMessages.RemoteFolderPath)
                    End If

                Next
                ' The last folder in the folderPath is deleted
                folderName = folders(folders.Length - 1)

                If deleteSubDirectories Then
                    ' Call the recursive function to delete sub-folders.
                    DeleteWithSubFolders(folderName)
                Else
                    ' Call the function to delete the specified folder.
                    DeleteObject(folderName)
                End If

            End Sub

            ''' <summary>
            ''' Adds an asynchronous FTP request to the Request Queue.
            ''' </summary>
            ''' <param name="request">The asynchronous FTP request.</param>
            Private Sub AddRequestToRequestQueue(ByVal request As FTPRequest)

                ' Acquire the exclusive lock on networkStream
                Threading.Monitor.Enter(Me.requestQueue)
                ' Add the request to the list of pending requests.
                Me.requestQueue.Add(request)
                ' Releases the exclusive lock on networkStream
                Threading.Monitor.Exit(Me.requestQueue)

                ' If the background worker handling asynchronous operations 
                ' is not busy, put it to work.
                If Not Me.asyncOperationHandler.IsBusy Then
                    Me.asyncOperationHandler.RunWorkerAsync()
                End If

            End Sub

            ''' <summary>
            ''' Raises the appropriate events and puts the background worker 
            ''' to work on any pending asynchronous requests.
            ''' </summary>
            ''' <param name="sender">The background worker that will process 
            ''' this method.</param>
            ''' <param name="e">DoWorkEventArgs to store the outcome of the 
            ''' operation.</param>
            Private Sub asyncOperationHandler_DoWork(ByVal sender As Object, ByVal e As  _
                                                      ComponentModel.DoWorkEventArgs) _
                                                      Handles asyncOperationHandler.DoWork

                ' Acquire an exclusive lock on the requestQueue. 
                Threading.Monitor.Enter(Me.requestQueue)
                If Me.requestQueue.Count <> 0 Then
                    ' Get the 1st request from the list of pending 
                    ' asynchronous operations.
                    Try

                        Me.runningAsyncRequest = Me.requestQueue(0)

                        ' Remove it from the list.
                        Me.requestQueue.RemoveAt(0)

                    Finally

                        ' Releases the exclusive lock on requestQueue
                        Threading.Monitor.Exit(Me.requestQueue)

                    End Try

                    If Me.asyncOperationHandler.CancellationPending Then
                        e.Cancel = True
                    Else

                        ' Raise the appropriate begin event and perform the 
                        ' operation.                       
                        RaiseBeginEvent(Me.runningAsyncRequest.RequestType, e)
                    End If

                End If

            End Sub

            ''' <summary>
            '''Event handler for background worker's RunWorkerCompleted event.
            ''' This method packs the outcome of an asynchronous operation into
            ''' the appropriate EventArgs and raises the operation's Completed 
            ''' event if implemented. It then puts the background worker to work
            ''' on any pending asynchronous requests from the request queue.
            ''' </summary>
            ''' <param name="sender">The background worker that will process 
            ''' this method.</param>
            ''' <param name="e">RunWorkerCompletedEventArgs which stores the 
            ''' outcome of the operation.</param>
            Private Sub asyncOperationHandler_RunWorkerCompleted(ByVal sender As Object, _
                                                                  ByVal e As ComponentModel.RunWorkerCompletedEventArgs) _
                                                                  Handles asyncOperationHandler.RunWorkerCompleted

                If Me.runningAsyncRequest IsNot Nothing Then
                    ' Raise the appropriate event.
                    Select Case Me.runningAsyncRequest.RequestType
                        Case FTPRequestType.GetFile

                            ' If Me.GetFileCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing
                            'Dim fileContents As Byte() = New Byte(-1) {}
                            Dim fileContents(0) As Byte

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then

                                ftpException = CType(e.Result, Exception)
                            Else
                                fileContents(0) = CByte(e.Result)
                            End If

                            ' Raise the event.
                            RaiseEvent GetFileCompleted(Me, New GetFileCompletedEventArgs _
                                                        (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                         fileContents, ftpException, e.Cancelled, _
                                                         Me.runningAsyncRequest.UserState))

                            ' End If
                            Exit Select

                        Case FTPRequestType.GetFolder

                            ' If Me.GetFolderCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If
                            ' Raise the event.
                            RaiseEvent GetFolderCompleted(Me, New GetFolderCompletedEventArgs _
                                                          (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                           Me.runningAsyncRequest.RequestParameters(1).ToString(), _
                                                           ftpException, e.Cancelled, Me.runningAsyncRequest.UserState))

                            ' End If
                            Exit Select

                        Case FTPRequestType.SendFile

                            ' If Me.SendFileCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If

                            ' Raise the event.
                            RaiseEvent SendFileCompleted(Me, New SendFileCompletedEventArgs _
                                                         (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                          ftpException, e.Cancelled, Me.runningAsyncRequest.UserState))
                            ' End If

                            Exit Select
                        Case FTPRequestType.SendFolder

                            ' If Me.SendFolderCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If

                            ' Raise the event.
                            RaiseEvent SendFolderCompleted(Me, New SendFolderCompletedEventArgs _
                                                           (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                            ftpException, e.Cancelled, Me.runningAsyncRequest.UserState))
                            ' End If

                            Exit Select

                        Case FTPRequestType.DeleteFile

                            ' If Me.DeleteFileCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing
                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If
                            ' Raise the event.
                            RaiseEvent DeleteFileCompleted(Me, New DeleteFileCompletedEventArgs _
                                                           (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                            ftpException, e.Cancelled, Me.runningAsyncRequest.UserState))
                            ' End If
                            Exit Select

                        Case FTPRequestType.DeleteFolder

                            ' If Me.DeleteFolderCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If

                            ' Raise the event.
                            RaiseEvent DeleteFolderCompleted(Me, New DeleteFolderCompletedEventArgs _
                                                             (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                              CBool(Me.runningAsyncRequest.RequestParameters(1)), ftpException, _
                                                              e.Cancelled, Me.runningAsyncRequest.UserState))
                            ' End If
                            Exit Select

                        Case FTPRequestType.CreateFolder

                            ' If Me.CreateFolderCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If

                            ' Raise the event.
                            RaiseEvent CreateFolderCompleted(Me, New CreateFolderCompletedEventArgs _
                                                             (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                              CBool(Me.runningAsyncRequest.RequestParameters(1)), _
                                                              ftpException, e.Cancelled, Me.runningAsyncRequest.UserState))
                            ' End If

                            Exit Select

                        Case FTPRequestType.SetCurrentDirectory

                            ' If Me.SetCurrentDirectoryCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)

                            End If

                            ' Raise the event.
                            RaiseEvent SetCurrentDirectoryCompleted(Me, New SetCurrentDirectoryCompletedEventArgs _
                                                                    (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                                     ftpException, e.Cancelled, Me.runningAsyncRequest.UserState))
                            ' End If
                            Exit Select

                        Case FTPRequestType.GetFolderListing

                            ' If Me.GetFolderListingCompleted IsNot Nothing Then
                            Dim ftpException As Exception = Nothing
                            Dim folderListing As New Xml.XmlDocument()

                            ' If an error has occured then set exception 
                            ' parameter of completed event
                            If e.Error IsNot Nothing Then
                                ftpException = e.Error

                            ElseIf Not e.Cancelled AndAlso e.Result IsNot Nothing AndAlso (TypeOf e.Result Is Exception) Then
                                ftpException = CType(e.Result, Exception)
                            Else
                                folderListing = CType(e.Result, Xml.XmlDocument)

                            End If

                            ' Raise the event.
                            RaiseEvent GetFolderListingCompleted(Me, New GetFolderListingCompletedEventArgs _
                                                                 (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                                  folderListing, ftpException, e.Cancelled, _
                                                                  Me.runningAsyncRequest.UserState))
                            ' End If
                            Exit Select

                    End Select

                End If

                ' If there are pending asynchronous requests, set the 
                ' background worker to work on them.
                If Me.requestQueue.Count > 0 Then
                    Me.asyncOperationHandler.RunWorkerAsync()
                End If

            End Sub

            ''' <summary>
            ''' Raises the begin event and performs the operation as specified 
            ''' by the ftpRequestType variable.
            ''' </summary>
            ''' <param name="ftpRequestType">Specifies the operation to 
            ''' be performed</param>
            ''' <param name="e">EventArgs of Begin event.</param>
            Private Sub RaiseBeginEvent(ByVal ftpRequestType As FTPRequestType, _
                                         ByVal e As ComponentModel.DoWorkEventArgs)

                Select Case ftpRequestType

                    Case ftpRequestType.GetFile

                        ' Raise the GetFile Begin event if required.
                        RaiseEvent GetFileBegin(Me, New GetFileBeginEventArgs _
                                                (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                 Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the netwrkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try

                            ' Perform the operation.
                            Dim fileContent As Byte() = GetFileObject(Me.runningAsyncRequest.RequestParameters(0).ToString())
                            e.Result = fileContent

                        Catch ex As Exception
                            e.Result = ex

                        Finally

                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)

                        End Try

                        Exit Select

                    Case ftpRequestType.GetFolder

                        ' Raise the GetFolderBegin event if required.
                        RaiseEvent GetFolderBegin(Me, New GetFolderBeginEventArgs _
                                                  (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                   Me.runningAsyncRequest.RequestParameters(1).ToString(), _
                                                   Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try
                            GetFolderObject(Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                            Me.runningAsyncRequest.RequestParameters(1).ToString())
                        Catch ex As Exception
                            e.Result = ex

                        Finally

                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)

                        End Try

                        Exit Select

                    Case ftpRequestType.SendFile

                        ' Raise the SendFileBegin event if required.
                        RaiseEvent SendFileBegin(Me, New SendFileBeginEventArgs _
                                                 (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                  Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try
                            If Me.runningAsyncRequest.RequestParameters.Length = 2 _
                            AndAlso TypeOf Me.runningAsyncRequest.RequestParameters(1) _
                            Is IO.MemoryStream Then

                                SendFileObject(CType(Me.runningAsyncRequest.RequestParameters(1),  _
                                               IO.MemoryStream), Me.runningAsyncRequest.RequestParameters(0).ToString())

                            Else

                                SendFileObject(Me.runningAsyncRequest.RequestParameters(0).ToString())
                                ' Perform the operation.
                            End If

                        Catch ex As Exception
                            e.Result = ex

                        Finally

                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)

                        End Try

                        Exit Select

                    Case ftpRequestType.SendFolder

                        ' Raise the SendFolderBegin event if required.
                        RaiseEvent SendFolderBegin(Me, New SendFolderBeginEventArgs _
                                                   (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                    Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try
                            SendFolderObject(Me.runningAsyncRequest.RequestParameters(0).ToString())
                        Catch ex As Exception
                            e.Result = ex

                        Finally
                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)

                        End Try

                        Exit Select

                    Case ftpRequestType.DeleteFile

                        ' Raise the DeleteFileBegin event if required.
                        RaiseEvent DeleteFileBegin(Me, New DeleteFileBeginEventArgs _
                                                   (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                    Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        ' Perform the operation.
                        Try
                            DeleteFileObject(Me.runningAsyncRequest.RequestParameters(0).ToString())
                        Catch ex As Exception
                            e.Result = ex

                        Finally

                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)

                        End Try

                        Exit Select

                    Case ftpRequestType.DeleteFolder

                        ' Raise the DeleteFolderBegin event if required.
                        RaiseEvent DeleteFolderBegin(Me, New DeleteFolderBeginEventArgs _
                                                     (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                      CBool(Me.runningAsyncRequest.RequestParameters(1)), _
                                                      Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try
                            ' Perform the operation.
                            DeleteFolderObject(Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                               CBool(Me.runningAsyncRequest.RequestParameters(1)))
                        Catch ex As Exception
                            e.Result = ex
                        Finally

                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)

                        End Try

                        Exit Select

                    Case ftpRequestType.CreateFolder

                        ' Raise the CreateFolderBegin event if required.
                        RaiseEvent CreateFolderBegin(Me, New CreateFolderBeginEventArgs _
                                                     (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                      CBool(Me.runningAsyncRequest.RequestParameters(1)), _
                                                      Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try
                            ' Perform the operation.
                            CreateFolderStructure(Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                  CBool(Me.runningAsyncRequest.RequestParameters(1)))
                        Catch ex As Exception
                            e.Result = ex

                        Finally
                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)
                        End Try

                        Exit Select

                    Case ftpRequestType.SetCurrentDirectory

                        ' Raise the SetCurrentDirectoryBegin event if required.
                        RaiseEvent SetCurrentDirectoryBegin(Me, New SetCurrentDirectoryBeginEventArgs _
                                                            (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                             Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)


                        Try
                            ' Perform the operation.
                            SetCurrentDirectoryObject(Me.runningAsyncRequest.RequestParameters(0).ToString())
                        Catch ex As Exception
                            e.Result = ex
                        Finally
                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)
                        End Try
                        Exit Select
                    Case ftpRequestType.GetFolderListing
                        ' Raise the SetCurrentDirectoryBegin event if required.

                        RaiseEvent GetFolderListingBegin(Me, New GetFolderListingBeginEventArgs _
                                                         (Me.runningAsyncRequest.RequestParameters(0).ToString(), _
                                                          Me.runningAsyncRequest.UserState))

                        ' Acquire an exclusive lock on the networkStream. 
                        Threading.Monitor.Enter(Me.netwrkStream)

                        Try
                            ' Perform the operation.
                            Dim folderListing As Xml.XmlDocument = GetFolderListingObject _
                            (Me.runningAsyncRequest.RequestParameters(0).ToString())

                            e.Result = folderListing
                        Catch ex As Exception
                            e.Result = ex
                        Finally
                            ' Releases the exclusive lock on networkStream
                            Threading.Monitor.Exit(Me.netwrkStream)
                        End Try

                        Exit Select

                End Select

            End Sub

#End Region

#Region "Public Properties"

            ''' <summary>
            ''' Gets or sets the network stream used for communicating with a remote device.
            ''' </summary>
            <ComponentModel.Browsable(False)> _
            Public Property NetworkStream() As Net.Sockets.NetworkStream

                Get
                    Return Me.netwrkStream
                End Get

                Set(ByVal value As Net.Sockets.NetworkStream)
                    Me.netwrkStream = value
                End Set

            End Property

#End Region

        End Class

    End Namespace

End Namespace
